//
//  SimWebView.m
//  Knowbox
//
//  Created by huxiulei on 14/11/20.
//  Copyright (c) 2014年 knowin. All rights reserved.
//

#import "SimWebView.h"
#import "UIColor+SimAdditions.h"
#import "UIImage+SimAdditions.h"
#import "SimImagePickerKit.h"
#import <SDWebImage/SDImageCache.h>
#import <SDWebImage/SDWebImagePrefetcher.h>
#import "SimEmptyView.h"
#import "UIView+SimAdditions.h"
#import "SimLoading.h"
#import "SimCommonData.h"

NSString * const kSimWebListenAudioStopNoti = @"kSimWebListenAudioStopNoti";

SimImpValue(kSimWebImageFailedIcon, NSString *);
SimImpValue(kSimWebImageFailedText, NSString *);

SimImpValue(kSimWebCSSRemoteURLStr, NSString *);
SimImpValue(kSimWebCSSLocalFilePath, NSString *);
SimImpValue(kSimWebJSRemoteURLStr, NSString *);
SimImpValue(kSimWebJSLocalFilePath, NSString *);

#define kInnerClickOnImagePrefix @"webimage:click:"

#define LOADING_BAR_HEIGHT 2

/* Unique URL triggered when JavaScript reports page load is complete */
static NSString *kCompleteRPCURL = @"webviewprogress:///complete";
static NSString *kInnnerQuestionLinker = @"KNPIC";

static const float kInitialProgressValue                = 0.1f;
static const float kBeforeInteractiveMaxProgressValue   = 0.5f;
static const float kAfterInteractiveMaxProgressValue    = 0.9f;

@interface ActivityWebLoadingView : UIView
@end

@implementation ActivityWebLoadingView
- (void)tintColorDidChange { self.backgroundColor = self.tintColor; }
@end

@interface SimWebView ()
{
    NSString *_localImageHtmlStr;
    NSMutableDictionary *_prefetchImageDict;
    NSInteger _unloadImageURLCount;
    UIView *_imageLoadingBgView;
    
    BOOL _tempDisbaleScroll;
    UIImageView *_reloadPreviewView;
}

@property (nonatomic, strong) SDWebImagePrefetcher *imagePrefetcher;

@end

@implementation SimWebView

+ (void)initialize
{
    NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    
    UIWebView *webView = [[UIWebView alloc] init];
    NSString* secretAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
    NSString *appendInfo = [NSString stringWithFormat:@" AppOS/iOS AppFrom/%@ AppVersion/", appID];
    NSString *curVersionInfo = [appendInfo stringByAppendingString:appVersion];
    if ([secretAgent hasSuffix:curVersionInfo] == NO) { //当前未设置正确代理
        NSRange agentRange = [secretAgent rangeOfString:appendInfo];
        if (agentRange.location != NSNotFound) { //设置过代理, 但版本是旧版本, 去除之前的设置
            secretAgent = [secretAgent stringByReplacingCharactersInRange:NSMakeRange(agentRange.location, agentRange.length-agentRange.location) withString:@""];
        }
        
        secretAgent = [secretAgent stringByAppendingString:curVersionInfo];
        [[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent" : secretAgent}];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.autoresizingMask = 0;
        self.backgroundColor = [UIColor whiteColor];
        self.clipsToBounds = YES;
        self.delegate = self;
        self.dataDetectorTypes = UIDataDetectorTypeNone;
        self.scrollView.bounces = NO;
        self.opaque = NO;
        _fontSize =  -1;//15;
        _lineHeight = 1.6;
        _textColor = nil; //HEXRGBCOLOR(0x5e6166);
        _autoFitType = WebViewAutoFitHeight;
        _bShowDetailPic = YES;
        
        if (!ABOVE_IOS7) {
            for (UIView *view in [self.scrollView subviews]) {
                if ([view isKindOfClass:[UIImageView class]]) {
                    view.hidden = YES;
                }
            }
        }
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopListenAudioNoti) name:kSimWebListenAudioStopNoti object:nil];
    }
    return self;
}

- (void)dealloc
{
    NSLog(@"SimWebView dealloc");
    //    [self stopAllAudio];
    [self resetImagePrefeter];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)stopListenAudioNoti
{
    [self stopAllAudio];
}

#pragma mark -
- (BOOL)isHtmlContent
{
    return _htmlContent.length > 0;
}

- (BOOL)isContentFinishLoad
{
    return (_finishStatus == WFS_Loaded && [self isImageFinishLoad]);
}

- (BOOL)isImageFinishLoad
{
    return (_unloadImageURLCount == 0 && _imagePrefetcher == nil);
}

- (UIColor *)webViewPageBackgroundColor
{
    //Pull the current background colour from the web view
    NSString *rgbString = [self stringByEvaluatingJavaScriptFromString:@"window.getComputedStyle(document.body,null).getPropertyValue('background-color');"];
    
    //if it wasn't found, or if it isn't a proper rgb value, just return white as the default
    if ([rgbString length] == 0 || [rgbString rangeOfString:@"rgb"].location == NSNotFound)
        return [UIColor whiteColor];
    
    //Assuming now the input is either 'rgb(255, 0, 0)' or 'rgba(255, 0, 0, 255)'
    
    //remove the 'rgba' componenet
    rgbString = [rgbString stringByReplacingOccurrencesOfString:@"rgba" withString:@""];
    //conversely, remove the 'rgb' component
    rgbString = [rgbString stringByReplacingOccurrencesOfString:@"rgb" withString:@""];
    //remove the brackets
    rgbString = [rgbString stringByReplacingOccurrencesOfString:@"(" withString:@""];
    rgbString = [rgbString stringByReplacingOccurrencesOfString:@")" withString:@""];
    //remove all spaces
    rgbString = [rgbString stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    //we should now have something like '0,0,0'. Split it up via the commas
    NSArray *componenets = [rgbString componentsSeparatedByString:@","];
    
    //Final output componenets
    CGFloat red, green, blue, alpha = 1.0f;
    
    //if the alpha value is 0, this indicates the RGB value wasn't actually set in the page, so just return white
    if ([componenets count] < 3 || ([componenets count] >= 4 && [[componenets objectAtIndex:3] integerValue] == 0))
        return [UIColor whiteColor];
    
    red     = (CGFloat)[[componenets objectAtIndex:0] integerValue] / 255.0f;
    green   = (CGFloat)[[componenets objectAtIndex:1] integerValue] / 255.0f;
    blue    = (CGFloat)[[componenets objectAtIndex:2] integerValue] / 255.0f;
    
    if ([componenets count] >= 4)
        alpha = (CGFloat)[[componenets objectAtIndex:3] integerValue] / 255.0f;
    
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

- (void)reloadWebView
{
    if (_showLoadingBar && self.isLoading) {
        self.loadingBarView.alpha = 0.0f;
    }
    [self stopLoading];
    
    if (self.webviewURL != nil) {
        NSURLRequest *request = self.request;
        if (self.request.URL.absoluteString.length == 0){
            request = [NSURLRequest requestWithURL:self.webviewURL
                                       cachePolicy:self.cachePolicy
                                   timeoutInterval:self.requestInterval];
            [self loadRequest:request];
        }
        else {
            [self doReloadWeb];
        }
    }
    
    if (_reLoad) {
        _reLoad();
    }
}


- (void)doReloadWeb
{
    if (_reloadPreviewView) {
        [_reloadPreviewView removeFromSuperview];
        _reloadPreviewView = nil;
    }
    
    UIImage *image = [UIImage imageFromView:self];
    _reloadPreviewView = [[UIImageView alloc] initWithImage:image];
    if (CGRectEqualToRect(_reloadPreviewView.bounds, self.bounds)) {
        [self addSubview:_reloadPreviewView];
    }
    [self reload];
}

- (void)stopAllAudio
{
    [self stringByEvaluatingJavaScriptFromString:@"stopPlay();"];
}

#pragma mark - URL
- (void)loadURL:(NSURL *)URL complete:(WebViewCompleteLoad)complete
{
    if (_webviewURL == URL && _finishStatus == WFS_Loaded) {
        if (_completeLoad) {
            _completeLoad(self, _finishStatus);
        }
        return;
    }
    
    _scrollSize = CGSizeZero;
    _webviewURL = URL;
    _completeLoad = complete;
    _finishStatus = WFS_None;
    if (_webviewURL) {
        NSURLRequest *request = [NSURLRequest requestWithURL:_webviewURL
                                                 cachePolicy:self.cachePolicy
                                             timeoutInterval:self.requestInterval];
        [self loadRequest:request];
    }
}

- (void)loadURLStr:(NSString *)URLStr complete:(WebViewCompleteLoad)complete
{
    NSURL *url = [NSURL URLWithString:[URLStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    if (!url) {
        url = [NSURL URLWithString:URLStr];
    };
    
    [self loadURL:url complete:complete];
}


#pragma mark - html content
- (void)loadHTMLString:(NSString *)string complete:(WebViewCompleteLoad)complete
{
    if ([_htmlContent isEqualToString:string] && [self isContentFinishLoad]) {
        if (_completeLoad) {
            _completeLoad(self, _finishStatus);
        }
        return;
    }
    
    _htmlContent = string ? : @"";
    _completeLoad = complete;
    [self setupImagePrefeter:_htmlContent];
    if (_localImageHtmlStr.length > 0) {
        [self prefetchImageURL];
    }
    else{
        [self loadHtmlContent];
    }
}

- (void)loadHtmlContent
{
    [self stopLoading];
    
    _scrollSize = CGSizeZero;
    _finishStatus = WFS_None;
    if (_htmlContent.length > 0) {
        NSString *formatHtml = [self formatedHtmlContent];
        
        if (self.scrollView.scrollEnabled) {
            _tempDisbaleScroll = YES;
            self.scrollView.scrollEnabled = NO;
        }
        [self loadHTMLString:formatHtml baseURL:nil];
    }
    else{
        self.height = 30;
        _finishStatus = WFS_Loaded;
        if (_completeLoad) {
            _completeLoad(self, _finishStatus);
        }
    }
}

- (void)didMoveToWindow
{
    [super didMoveToWindow];
    if (self.window == nil && self.superview != nil) {
        [self stopAllAudio];
    }
}

- (NSString *)formatedHtmlContent
{
    
    NSString *numStr = @"";
    if (_orderNum > 0) {
        numStr = [NSString stringWithFormat:@"<span style=\"background:#8f8f8f;color:#fff;padding:0px 4px 0px 4px;float:left;font-size:%fpx;font-family:'Arial';border-radius:2px;-moz-border-radius:2px; -webkit-border-radius:2px;\">%ld</span>&nbsp;&nbsp;", _fontSize-2, (long)_orderNum];
    }
    
    
    NSString *remoteCssUrlStr = SimValue(kSimWebCSSRemoteURLStr, @"http://7xjnvd.com2.z0.glb.qiniucdn.com/llkt_201604141934.css");
    NSString *localCssPath = SimValue(kSimWebCSSLocalFilePath, nil);
    
    NSString *remoteJsUrlStr = SimValue(kSimWebJSRemoteURLStr, @"http://7xohdn.com2.z0.glb.qiniucdn.com/resource/bundle_20160505.js");
    NSString *localJsPath = SimValue(kSimWebJSLocalFilePath, nil);
    
    NSString *htmlContent = _localImageHtmlStr ? :_htmlContent;
    if (localCssPath.length > 0) {
        NSString *patternStr = [NSString stringWithFormat:@"<link[^>]+href=['\"]%@['\"][^>]*>", remoteCssUrlStr];
        NSRegularExpression *imgRegex = [NSRegularExpression regularExpressionWithPattern:patternStr options:NSRegularExpressionAllowCommentsAndWhitespace | NSRegularExpressionCaseInsensitive error:nil];
        NSArray *regexResult = [imgRegex matchesInString:htmlContent options:NSMatchingReportCompletion range:NSMakeRange(0, htmlContent.length)];
        if (regexResult.count > 0) {
            NSMutableArray *replaceStrs = [NSMutableArray array];
            for (NSTextCheckingResult *resut in regexResult){
                [replaceStrs addObject:[htmlContent substringWithRange:resut.range]];
            }
            for (NSString *regexStr in replaceStrs) {
                htmlContent = [htmlContent stringByReplacingOccurrencesOfString:regexStr withString:@""];
            }
        }
        
        
        htmlContent = [htmlContent stringByAppendingFormat:@"<link href=\"file://%@\" rel=\"stylesheet\" type=\"text/css\"/>", localCssPath];
        
    }
    
    NSString *fontSizeStyle = _fontSize > 0 ? [NSString stringWithFormat:@"font-size:%fpx;", _fontSize] : @"";
    NSString *lineHeightStyle = _lineHeight > 0 ? [NSString stringWithFormat:@"line-height: %f;", _lineHeight] : @"";
    NSString *clorStyle = _textColor != nil ? [NSString stringWithFormat:@"color:#%@", [_textColor hexStringFromColor]] : @"";
    
    NSString *formatHtml =  [NSString stringWithFormat:@"<!DOCTYPE html><html>\n"
                             "<head>\n"
                             "<script type=\"text/javascript\">\n"
                             "window.onload=function(){\n"
                             "for(var i=0;i< document.getElementsByTagName(\"img\").length;i++)"
                             "{var imgeElement = document.getElementsByTagName(\"img\")[i];"
                             "imgeElement.style.maxWidth=\"%fpx\";" //图片自适应缩放
                             "imgeElement.onclick=function()"       //图片点击处理
                             "{document.location=\"%@\"+this.src;};"
                             "}}"
                             "</script>\n"
                             "<style type=\"text/css\"> \n"
                             "body {%@%@%@ }\n"
                             "</style> \n"
                             "</head> \n"
                             "<body>%@%@"
                             "<script src=%@></script>"
                             "</body>"
                             "</html>",
                             self.width-20,
                             kInnerClickOnImagePrefix,
                             fontSizeStyle,
                             lineHeightStyle,
                             clorStyle,
                             numStr,
                             htmlContent,
                             localJsPath ? [NSString stringWithFormat:@"file://%@", localJsPath] : remoteJsUrlStr];
    
    return formatHtml;
}

#pragma mark -

- (void)updateContentSize
{
    _scrollSize.height = [[self stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"] floatValue];
    _scrollSize.width = [[self stringByEvaluatingJavaScriptFromString:@"document.body.scrollWidth;"] floatValue];
    if (_tempDisbaleScroll) {
        self.scrollView.scrollEnabled = YES;
    }
//    NSLog(@"_scrollSize:%@", NSStringFromCGSize(_scrollSize));

    if (_autoFitType & WebViewAutoFitHeight) {
        self.height =  _scrollSize.width == 0 ? 0 : ceil(self.width * _scrollSize.height / _scrollSize.width);
    }
    if (_autoFitType & WebViewAutoFitWidth) {
        self.width = _scrollSize.height == 0 ? 0 : ceil(self.height * _scrollSize.width / _scrollSize.height);
    }
}

- (void)handleLoadRequestCompletion:(NSError *)error
{
    //decrement the number of concurrent requests
    _loadingProgressState.loadingCount--;
    
    //update the progress bar
    [self incrementLoadProgress];
    
    //Query the webview to see what load state JavaScript perceives it at
    NSString *readyState = [self stringByEvaluatingJavaScriptFromString:@"document.readyState"];
    
    //interactive means the page has loaded sufficiently to allow user interaction now
    BOOL interactive = [readyState isEqualToString:@"interactive"];
    if (interactive){
        _loadingProgressState.interactive = YES;
        
        //if we're at the interactive state, attach a Javascript listener to inform us when the page has fully loaded
        NSString *waitForCompleteJS = [NSString stringWithFormat:   @"window.addEventListener('load',function() { "
                                       @"var iframe = document.createElement('iframe');"
                                       @"iframe.style.display = 'none';"
                                       @"iframe.src = '%@';"
                                       @"document.body.appendChild(iframe);"
                                       @"}, false);", kCompleteRPCURL];
        
        [self stringByEvaluatingJavaScriptFromString:waitForCompleteJS];
        
        //finally, if the app desires it, disable the ability to tap and hold on links
        if (self.disableContextualPopupMenu)
            [self stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitTouchCallout='none';"];
    }
    else{
        [self finishLoadProgress:error];
    }
}

- (BOOL)handlerRequest:(NSString *)requestStr navigationType:(UIWebViewNavigationType)navigationType
{
    if (navigationType == UIWebViewNavigationTypeLinkClicked && [requestStr hasSuffix:@"KNPIC"]) {
        return YES; //处理结束，后续不再处理
    }
    
    if (self.bShowDetailPic) {
        if ([requestStr hasPrefix:kInnerClickOnImagePrefix]) {
            requestStr = [requestStr substringFromIndex:[kInnerClickOnImagePrefix length]];
            [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:requestStr]
                                                            options:0
                                                           progress:nil
                                                          completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
                                                              if (image && (image.size.width * image.size.height > 2000)) {
                                                                  UIViewController *vc = self.viewController;
                                                                  if (vc != nil) {
                                                                      SimImagePickerKit *kit = [SimImagePickerKit instance];
                                                                      kit.imageContents = @[image];
                                                                      SimPhotoBrowser *photoBrowser = [kit showImageBrowserInVC:vc];
                                                                      photoBrowser.zoomScrollViewBgColor = [UIColor whiteColor];
                                                                  }
                                                                  
                                                              }
                                                          }];
            return YES;
        }
    }
    
    return NO;
}

#pragma mark - html image load
- (void)resetImagePrefeter
{
    if (_imagePrefetcher) {
        [_imagePrefetcher cancelPrefetching];
        _imagePrefetcher = nil;
    }
    _unloadImageURLCount = 0;
    _prefetchImageDict = nil;
    _localImageHtmlStr = nil;
}

- (void)setupImagePrefeter:(NSString *)htmlStr
{
    @autoreleasepool {
        [self resetImagePrefeter];
        
        NSRegularExpression *imgRegex = [NSRegularExpression regularExpressionWithPattern:@"<img[^>]+src=['\"]([^'\"]+)['\"][^>]*>" options:NSRegularExpressionAllowCommentsAndWhitespace | NSRegularExpressionCaseInsensitive error:nil];
        NSArray *regexResult = [imgRegex matchesInString:htmlStr options:NSMatchingReportCompletion range:NSMakeRange(0, htmlStr.length)];
        if (regexResult.count > 0) {
            for (NSTextCheckingResult *resut in regexResult){
                NSString *imageHtml = [htmlStr substringWithRange:resut.range];
                NSArray *tmpArray = [imageHtml componentsSeparatedByString:@"src=\""];
                if (tmpArray.count >= 2) {
                    NSString *src = tmpArray[1];
                    NSUInteger loc = [src rangeOfString:@"\""].location;
                    if (loc != NSNotFound) {
                        src = [src substringToIndex:loc];
                        if ([src hasPrefix:@"http"]) {
                            NSURL *url = [NSURL URLWithString:src];
                            if (url) {
                                NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
                                NSString *filePath = [[SDImageCache sharedImageCache] defaultCachePathForKey:key];
                                if (!_prefetchImageDict) {
                                    _prefetchImageDict = [NSMutableDictionary dictionary];
                                }
                                _prefetchImageDict[src] = filePath;
                            }
                        }
                    }
                }
            }
            
            for (NSString *src in _prefetchImageDict.allKeys) {
                NSString *localPath = [_prefetchImageDict objectForKey:src];
                htmlStr = [htmlStr stringByReplacingOccurrencesOfString:src
                                                             withString:[@"file://" stringByAppendingString:localPath]];
            }
            
            _localImageHtmlStr = [htmlStr copy];
        }
    }
}

- (void)prefetchImageURL
{
    NSMutableArray *fetchURLs = nil;
    NSFileManager *fm = [NSFileManager defaultManager];
    for (NSString *src in _prefetchImageDict.allKeys) {
        NSString *localPath = [_prefetchImageDict objectForKey:src];
        if (![fm fileExistsAtPath:localPath]) {
            if (!fetchURLs) {
                fetchURLs = [[NSMutableArray alloc] init];
            }
            [fetchURLs addObject:[NSURL URLWithString:src]];
        }
    }
    
    if (fetchURLs.count > 0) {
        [self resetImagePrefeter];
        
        NSLog(@"fetchURLs:%@", fetchURLs);
        DefineWeak(self);
        _imagePrefetcher = [[SDWebImagePrefetcher alloc] init];
        _imagePrefetcher.maxConcurrentDownloads = 1;
        [_imagePrefetcher prefetchURLs:fetchURLs progress:nil completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
            [Weak(self) finishLoadHtmlImage:noOfFinishedUrls skipCount:noOfSkippedUrls];
        }];
    }
    else{
        [self loadHtmlContent];
    }
}

- (void)finishLoadHtmlImage:(NSUInteger)finishCount skipCount:(NSUInteger)skipCount
{
    NSLog(@"finishLoadHtmlImage:%td", finishCount);
    _unloadImageURLCount = skipCount;
    _imagePrefetcher = nil;
    
    if (_unloadImageURLCount > 0) {
        [self loadHtmlContent];
    }
    else{
        NSFileManager *fm = [NSFileManager defaultManager];
        BOOL fileIsSaving = YES;
        while (fileIsSaving) {
            fileIsSaving = NO;
            for (NSString *src in _prefetchImageDict.allKeys) {
                NSString *localPath = [_prefetchImageDict objectForKey:src];
                if (![fm fileExistsAtPath:localPath]) {
                    fileIsSaving = YES;
                    break;
                }
            }
            
            [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]];
        }
        
        [self loadHtmlContent];
    }
}

#pragma mark - WebView Delegate

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    //if the URL is the load completed notification from JavaScript
    if ([request.URL.absoluteString isEqualToString:kCompleteRPCURL]) {
        [self finishLoadProgress:nil];
        return NO;
    }
    
    if (self.shouldStartLoadRequestHandler){
        return  self.shouldStartLoadRequestHandler(request, navigationType);
    }
    else{
        NSString *requestString = [[request URL] absoluteString];
        BOOL hasHandleReqeust = [self handlerRequest:requestString navigationType:navigationType];
        if (hasHandleReqeust) {
            return NO;
        }
        else{
            if (![self isHtmlContent]) {
                BOOL isFragmentJump = NO;
                if (request.URL.fragment){
                    NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""];
                    isFragmentJump = [nonFragmentURL isEqualToString:webView.request.URL.absoluteString];
                }
                
                BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL];
                BOOL isHTTP = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"];
                if (!isFragmentJump && isHTTP && isTopLevelNavigation && navigationType != UIWebViewNavigationTypeBackForward){
                    //Save the URL in the accessor property
                    _webviewURL = [request URL];
                    [self resetLoadProgress];
                }
            }
            
            return YES;
        }
    }
}

- (void)webViewDidStartLoad:(UIWebView *)webView
{
    _loadingProgressState.loadingCount++;
    _loadingProgressState.maxLoadCount = MAX(_loadingProgressState.maxLoadCount, _loadingProgressState.loadingCount);
    
    [self startLoadProgress];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [self performSelector:@selector(handleLoadRequestCompletion:) withObject:nil afterDelay:0.2];
    
//    [self handleLoadRequestCompletion:nil];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    
    NSString *URLErrorStr = error.userInfo[@"NSErrorFailingURLStringKey"];
    if ([URLErrorStr hasPrefix:@"hybird://method/"]) {
        return;
    }
    
    if (_showLoadingBar) {
        self.loadingBarView.alpha = 0.0f;
    }
    [self handleLoadRequestCompletion:error];
}

#pragma mark - progress
- (void)startLoadProgress
{
    if (_startLoad) {
        _startLoad();
    }
    
    //If we haven't started loading yet, set the progress to small, but visible value
    if (_showLoadingBar && _loadingProgressState.loadingProgress < kInitialProgressValue && self.isLoading)
    {
        if (_loadingBarView == nil) {
            CGFloat y = self.scrollView.contentInset.top;
            _loadingBarView = [[ActivityWebLoadingView alloc] initWithFrame:CGRectMake(0, y, CGRectGetWidth(self.frame), LOADING_BAR_HEIGHT)];
            self.loadingBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            
            if (!ABOVE_IOS7) {
                CAGradientLayer *loadingBarGradientLayer = [CAGradientLayer layer];
                loadingBarGradientLayer.colors = @[(id)[[UIColor colorWithWhite:0.0f alpha:0.25f] CGColor],(id)[[UIColor colorWithWhite:0.0f alpha:0.0f] CGColor]];
                loadingBarGradientLayer.frame = _loadingBarView.bounds;
                [_loadingBarView.layer addSublayer:loadingBarGradientLayer];
            }
        }
        
        if (self.loadingBarTintColor){
            if ([_loadingBarView respondsToSelector:@selector(setTintColor:)]) {
                _loadingBarView.tintColor = self.loadingBarTintColor;
            }
            else{
                _loadingBarView.backgroundColor = self.loadingBarTintColor;
            }
        }
        
        //reset the loading bar
        CGRect frame = self.loadingBarView.frame;
        frame.size.width = CGRectGetWidth(self.bounds);
        frame.origin.x = -frame.size.width;
        frame.origin.y = self.scrollView.contentInset.top;
        _loadingBarView.frame = frame;
        _loadingBarView.alpha = 1.0f;
        
        //add the loading bar to the view
        if (self.showLoadingBar)
            [self insertSubview:_loadingBarView aboveSubview:self];
        
        //kickstart the loading progress
        [self setLoadingProgress:kInitialProgressValue];
    }
}

- (void)finishLoadProgress:(NSError *)error
{
    if (_reloadPreviewView) {
        [_reloadPreviewView removeFromSuperview];
        _reloadPreviewView = nil;
    }
    
    [self setLoadingProgress:1.0f];
    [self updateContentSize];
    
    if (![self isImageFinishLoad]) {
        if (_imagePrefetcher != nil) {
            [self showImageLoading];
        }
        else if(_unloadImageURLCount > 0){
            [self showErrorTip];
        }
    }
    else{
        [self showMarkView:NO];;
    }
    
    _finishStatus = error == nil ? WFS_Loaded : WFS_LoadError;
    if (_completeLoad) {
        _completeLoad(self, _finishStatus);
    }
}

- (void)showMarkView:(BOOL)show
{
    if (show) {
        if (_imageLoadingBgView) {
            [self showMarkView:NO];
        }
        
        _imageLoadingBgView = [[UIView alloc] initWithFrame:self.bounds];
        _imageLoadingBgView.backgroundColor = [UIColor whiteColor];
        _imageLoadingBgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self addSubview:_imageLoadingBgView];
    }
    else{
        if (_imageLoadingBgView) {
            for (UIView *subview in _imageLoadingBgView.subviews) {
                if (IsKindOfClass(subview, UIActivityIndicatorView)) {
                    [(UIActivityIndicatorView *)subview stopAnimating];
                }
            }
            [SimEmptyView removeFromView:_imageLoadingBgView];
            [_imageLoadingBgView removeFromSuperview];
            _imageLoadingBgView = nil;
        }
    }
}

- (void)showImageLoading
{
    [self showMarkView:YES];
    if (_imageLoadingBgView.height < 50) {
        UIActivityIndicatorView *_indicatoreView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        _indicatoreView.center = CGPointMake(_imageLoadingBgView.width/2, _imageLoadingBgView.height/2);
        [_indicatoreView startAnimating];
        _indicatoreView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
        [_imageLoadingBgView addSubview:_indicatoreView];
    }
    else{
        [SimLoading showEmptyLoadingInView:_imageLoadingBgView];
    }
}

- (void)showErrorTip
{
    [self showMarkView:YES];
    DefineWeak(self);
    [SimEmptyView showInView:_imageLoadingBgView
                    iconName:SimValue(kSimWebImageFailedIcon,  @"icon_empty_error")
                     content:SimValue(kSimWebImageFailedText, @"题目图片加载失败\n点击重试加载")
                       touch:^{
                           [Weak(self) htmlFailLoadToRetry];
                       }];
}


- (void)htmlFailLoadToRetry
{
    //重新布局loading显示
    [self prefetchImageURL];
    if (![self isImageFinishLoad]) {
        [self showImageLoading];
    }
}

- (void)resetLoadProgress
{
    memset(&_loadingProgressState, 0, sizeof(_loadingProgressState));
    [self setLoadingProgress:0.0f];
    
    if (_resetLoad) {
        _resetLoad();
    }
}

- (void)incrementLoadProgress
{
    float progress          = _loadingProgressState.loadingProgress;
    float maxProgress       = _loadingProgressState.interactive ? kAfterInteractiveMaxProgressValue : kBeforeInteractiveMaxProgressValue;
    float remainingPercent  = (float)_loadingProgressState.loadingCount / (float)_loadingProgressState.maxLoadCount;
    float increment         = (maxProgress - progress) * remainingPercent;
    progress                = fmin((progress+increment), maxProgress);
    
    [self setLoadingProgress:progress];
}

- (void)setLoadingProgress:(CGFloat)loadingProgress
{
    if (loadingProgress > _loadingProgressState.loadingProgress || loadingProgress == 0){
        _loadingProgressState.loadingProgress = loadingProgress;
        if (_showLoadingBar){
            CGRect frame = self.loadingBarView.frame;
            frame.origin.x = -CGRectGetWidth(self.loadingBarView.frame) + (CGRectGetWidth(self.bounds) * _loadingProgressState.loadingProgress);
            
            [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.loadingBarView.frame = frame;
            } completion:^(BOOL finished) {
                if (loadingProgress >= 1.0f - FLT_EPSILON){
                    [UIView animateWithDuration:0.2f animations:^{
                        self.loadingBarView.alpha = 0.0f;
                    }];
                }
            }];
        }
    }
}


@end
